#include "StatisticGatherer.h"

#include "MachineDependents.h"
#include "PowerMonitor.h"
#include "CommandDispatcher.h"

StatisticGatherer::StatisticGatherer() : mtaskScheduler (TaskSchedulerSingleton::instance()), mextendDeviceManager(ExtendDeviceManagerSingleton::instance()) , minfoPersistor(OFFILE_STATISTIC_FILE){
    mstatisticInfos.reserve(200);

    CommandDispatcherSingleton::instance().mnetworkListeners.push_back(this);
}



StatisticGatherer::~StatisticGatherer(void) {
    //dtor
}



StatisticGatherer& StatisticGatherer::create(void){
    static StatisticGatherer i;

    return i;
}


void StatisticGatherer::gatherStatisticInfo(void) {
    ExtendDeviceWeakPtrs* pextendDeviceWeakPtrs = &ExtendDeviceManagerSingleton::instance().getExtendDevices(ExtendDeviceEnum::POWER);

    if (!pextendDeviceWeakPtrs->empty()) {
        ExtendDevicePtr devicePtr = pextendDeviceWeakPtrs->front().lock();
        if (devicePtr) {
            PowerMonitor* pPowerMonitor = static_cast <PowerMonitor*>(&*devicePtr);
            pPowerMonitor->updateInformation();
            mstatisticInfos.emplace_back(time(nullptr), pPowerMonitor->mkwh);

            LOG_DEDUG("%s,data:{mkwh:%s}", __FUNCTION__, pPowerMonitor->mkwh.data());
        }
    }

}



void StatisticGatherer::offline(INetwork* const network)  {

//    resetInfoPersistor();

    minfoPersistor.prepareForWrite();

    startupGather();
}

void StatisticGatherer::online(INetwork* const network)  {
//    resetInfoPersistor();

    stopGather();
}




void StatisticGatherer::saveStatisticInfos(void) {
    minfoPersistor.saveToFile(mstatisticInfos);
    mstatisticInfos.clear();
}



bool StatisticGatherer::startupGather(void) {
    LOG_DEDUG(__FUNCTION__);

    std::time_t currentTime = std::time(nullptr) + 1;
    DateTimeUtility::ClockTime_t triggerTime{currentTime * DateTimeUtility::ClockTime_t::period::den};
    TaskRecord* ptaskRecord = new TaskRecord(TaskletInfo{std::bind(&StatisticGatherer::gatherStatisticInfo, this), nullptr}, triggerTime, tick_count_t(60 * DateTimeUtility::ClockTime_t::period::den), ETT_CIRCLE);
    mtaskScheduler.makeOnlyOneTask(mwptrGatherTask, ptaskRecord);

    DateTimeUtility::ClockTime_t saveInterval{3600 * DateTimeUtility::ClockTime_t::period::den};
    DateTimeUtility::ClockTime_t saveTriggerTime{currentTime * DateTimeUtility::ClockTime_t::period::den};
    ptaskRecord = new TaskRecord(TaskletInfo{std::bind(&StatisticGatherer::saveStatisticInfos, this), nullptr}, saveTriggerTime + saveInterval, saveInterval, ETT_CIRCLE);
    mtaskScheduler.makeOnlyOneTask(mwptrSaveTask, ptaskRecord);

    return true;
}



bool StatisticGatherer::stopGather(void) {
    mtaskScheduler.cancelTask(mwptrGatherTask);
    mtaskScheduler.cancelTask(mwptrSaveTask);

    saveStatisticInfos();

    LOG_DEDUG(__FUNCTION__);

    return true;
}



void StatisticGatherer::resetInfoPersistor(void) {
    minfoPersistor.~StatisticInfoPersistor();
    new(&minfoPersistor) StatisticInfoPersistor(OFFILE_STATISTIC_FILE);
}


